package com.mapforge.gui;

import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

import javax.swing.BorderFactory;
import javax.swing.JTextField;
import javax.swing.Timer;
import javax.swing.border.Border;

/**
 * The {@link JTextFieldLabel} class is a {@link JTextField} that appears as a
 * label unless the user double clicks, or clicked and holds the field.
 * 
 * @author Will Morrison
 */
public class JTextFieldLabel extends JTextField {
	/**
	 * Default serial version ID, here to remove warnings
	 */
	private static final long serialVersionUID = 1L;

	/**
	 * The original border this JTextfield used upon first instantiation
	 */
	private Border origBorder;
	private static final Border emptyBorder = BorderFactory.createEmptyBorder();

	public JTextFieldLabel() {
		this("");
	}

	public JTextFieldLabel(String text) {
		super(text, 10);
		setEditable(false);
		setOpaque(false);
		origBorder = this.getBorder();
		privateSetBorder(emptyBorder);

		TextFieldLabelListener listener = new TextFieldLabelListener();
		addMouseListener(listener);
		addMouseMotionListener(listener);
		addFocusListener(listener);
		addActionListener(listener);
	}

	public void setBorder(Border b) {
		this.origBorder = b;
		super.setBorder(b);
	}

	private void privateSetBorder(Border b) {
		super.setBorder(b);
	}

	public void paintComponent(Graphics g) {
		if (!hasFocus()) {
			super.setBorder(emptyBorder);
		}
		super.paintComponent(g);
	}

	private class TextFieldLabelListener extends MouseAdapter implements
			FocusListener, ActionListener {
		private Timer timer;
		private boolean mouseHasMoved;

		public TextFieldLabelListener() {
			timer = new Timer(1000, this);
		}

		public void mouseClicked(MouseEvent e) {
			if (e.getClickCount() == 2) {
				setEditable(true);
				setOpaque(true);
				privateSetBorder(origBorder);
			}
		}

		public void mousePressed(MouseEvent e) {
			if (!timer.isRunning() && !mouseHasMoved) {
				timer.start();
			}
		}

		public void mouseDragged(MouseEvent e) {
			mouseHasMoved = true;
			timer.stop();
		}

		public void mouseReleased(MouseEvent e) {
			mouseHasMoved = false;
			timer.stop();
		}

		public void focusGained(FocusEvent e) {
			// intentionally left blank
		}

		public void focusLost(FocusEvent e) {
			privateSetBorder(emptyBorder);
			setEditable(false);
			setOpaque(false);
		}

		public void actionPerformed(ActionEvent e) {
			if (e.getSource() instanceof Timer) {
				timer.stop();
				privateSetBorder(origBorder);
				setEditable(true);
				setOpaque(true);
				requestFocus();
			} else {
				privateSetBorder(emptyBorder);
				setEditable(false);
				setOpaque(false);
			}
		}
	}
}